package com.angus.modules.content.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.angus.common.core.enums.ContentType;
import com.angus.modules.content.domain.*;
import com.angus.modules.content.dto.MyCollectionDto;
import com.angus.modules.content.repository.*;
import com.angus.modules.content.service.IMyCollectionService;
import com.angus.modules.content.vo.MyCollectionVo;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author lineCode
 */
@Service
public class MyCollectionServiceImpl implements IMyCollectionService {

    @Resource
    private CourseRepository courseRepository;

    @Resource
    private CNContentRepository cNContentRepository;

    @Resource
    private ENContentRepository eNContentRepository;

    @Resource
    private MyCollectionRepository myCollectionRepository;

    @Override
    public Boolean addCollection(MyCollectionDto dto, Long userId) {
        // 查询课程类型
        Course course = courseRepository.getCourseByCode(dto.getCourseCode());
        MyCollection myCollection = new MyCollection();
        myCollection.setGroupFlag(dto.getGroupFlag());
        myCollection.setGroupId(dto.getGroupId());
        myCollection.setCourseCode(dto.getCourseCode());
        myCollection.setUnitNum(dto.getUnitNum());
        myCollection.setContentType(course.getContentType());
        myCollection.setUserId(userId);
        myCollection.setDelFlag("0");
        return myCollectionRepository.save(myCollection);
    }

    @Override
    public Boolean cancelCollection(MyCollectionDto dto, Long userId) {
        return myCollectionRepository.remove(Wrappers.lambdaQuery(MyCollection.class)
                .eq(MyCollection::getGroupId, dto.getGroupId())
                .eq(MyCollection::getCourseCode, dto.getCourseCode())
                .eq(MyCollection::getUnitNum, dto.getUnitNum())
                .eq(MyCollection::getUserId, userId)
                .eq(MyCollection::getGroupFlag, dto.getGroupFlag())
                .eq(MyCollection::getDelFlag, 0));
    }

    @Override
    public Boolean cancelCollectionBatch(List<Long> ids, Long userId) {
        return myCollectionRepository.update(Wrappers.lambdaUpdate(MyCollection.class)
                .set(MyCollection::getDelFlag, 1)
                .in(MyCollection::getId, ids)
                .eq(MyCollection::getUserId, userId)
                .eq(MyCollection::getDelFlag, 0));
    }



    @Override
    public MyCollection queryCollection(MyCollectionDto dto, Long userId){
        return myCollectionRepository.getOne(Wrappers.lambdaQuery(MyCollection.class)
                .eq(MyCollection::getGroupId, dto.getGroupId())
                .eq(MyCollection::getCourseCode, dto.getCourseCode())
                .eq(MyCollection::getUnitNum, dto.getUnitNum())
                .eq(MyCollection::getUserId, userId)
                .eq(MyCollection::getGroupFlag, dto.getGroupFlag())
                .eq(MyCollection::getDelFlag, 0));
    }

    @Override
    public List<MyCollectionVo> getMyCollectionList(Long userId) {

        List<MyCollectionVo> vo = new ArrayList<>();

        // 获取用户全部收藏记录
        List<MyCollection> myCollectionList = myCollectionRepository.getMyCollectionList(userId);
        if (myCollectionList.isEmpty()) {
            return vo;
        }

        // 获取收藏的全部课程码
        List<String> courseCodeMap = extractDistinct(myCollectionList, MyCollection::getCourseCode);

        // 查询课程是否存在
        List<Course> list = courseRepository.list(Wrappers.lambdaQuery(Course.class).in(Course::getCourseCode, courseCodeMap));

        if (list.isEmpty()) {
            return vo;
        }

        // 获取 groupId
        List<Long> groupIdMap = extractDistinct(myCollectionList, MyCollection::getGroupId);

        // 获取 groupFlag
        List<String> groupFlagMap = extractDistinct(myCollectionList, MyCollection::getGroupFlag);

        Map<String, List<MyCollection>> contentMap = myCollectionList.stream()
                .collect(Collectors.groupingBy(MyCollection::getContentType));


        List<CNContent> allCNContent = cNContentRepository.list(Wrappers.lambdaQuery(CNContent.class)
                .in(CNContent::getCourseCode, courseCodeMap)
                .in(CNContent::getGroupId, groupIdMap)
                .in(CNContent::getGroupFlag, groupFlagMap));
        List<ENContent> allENContent = eNContentRepository.list(Wrappers.lambdaQuery(ENContent.class)
                .in(ENContent::getCourseCode, courseCodeMap)
                .in(ENContent::getGroupId, groupIdMap)
                .in(ENContent::getGroupFlag, groupFlagMap));

        for (Course course : list) {
            processContent(contentMap.getOrDefault(ContentType.CN.getTypeCode(), Collections.emptyList()), allCNContent, course, vo);
            processContent(contentMap.getOrDefault(ContentType.EN.getTypeCode(), Collections.emptyList()), allENContent, course, vo);
        }
        return vo;
    }
    private void processContent(List<MyCollection> myCollections, List<? extends Content> contents, Course course,  List<MyCollectionVo> result) {
        if (CollUtil.isNotEmpty(contents)) {
            for (MyCollection myCollection : myCollections) {
                for (Content content : contents) {
                    if (Objects.equals(myCollection.getCourseCode(), course.getCourseCode())
                            && Objects.equals(myCollection.getGroupFlag(), content.getGroupFlag())) {
                        MyCollectionVo vo = new MyCollectionVo();
                        vo.setId(myCollection.getId());
                        vo.setCourseCode(myCollection.getCourseCode());
                        vo.setGroupFlag(myCollection.getGroupFlag());
                        vo.setGroupId(myCollection.getGroupId());
                        vo.setUnitNum(myCollection.getUnitNum());
                        vo.setCreateTime(myCollection.getCreateTime());
                        vo.setContentType(myCollection.getContentType());
                        vo.setWord(content.getWord());
                        result.add(vo);
                    }
                }
            }
        }
    }

    public static <T, R> List<R> extractDistinct(List<T> list, Function<T, R> mapper) {
        return list.stream()
                .map(mapper)
                .distinct()
                .collect(Collectors.toList());
    }

}
